from multiprocessing.connection import Client
from typing import final

import pybloom_live
from gmpy2 import mpz
from mpmath import identify
from sympy.codegen import Print
from sympy.codegen.fnodes import ubound
from sympy.core.sympify import kernS

from bloom_filter import BloomFilter
import threshold_paillier
from paillier import decryption, encryption
from threshold_paillier import rerandomize, generate_random_number, multiply_homomorphically, add_homomorphically, \
    partial_decrypt, encrypt
from scp import secure_comparison_protocol


def main():
    # 创建布隆过滤器实例
    parties_t = 4
    threshold_l=1
    client_1_set = [1,2,3,4]
    client_2_set = [4,2,6,1]
    client_3_set = [3,2,1,7]
    server_set = [1,2,9,4]

    print("client_1_set = ",client_1_set)
    print("client_2_set = ",client_2_set)
    print("client_3_set = ", client_3_set)
    print("server_set = ",server_set)

    # 修改为 m_bits 和 k_hashes
    bloom_filter_1 = BloomFilter(m_bits=1000, k_hashes=3)
    bloom_filter_2 = BloomFilter(m_bits=1000, k_hashes=3)
    bloom_filter_3 = BloomFilter(m_bits=1000, k_hashes=3)

    k_hashes = bloom_filter_1.k_hashes

    # 生成BF1
    for num in client_1_set:
        bloom_filter_1.insert(num)
    # 生成BF2
    for num in client_2_set:
        bloom_filter_2.insert(num)
    #生成BF3
    for num in client_3_set:
        bloom_filter_3.insert(num)

    #先不需要反转了
    '''# 生成IBF1
    bloom_filter_1.invert()
    # 生成IBF2（根据你的需求）
    bloom_filter_2.invert()'''

    keys = threshold_paillier.key_gen(key_length=1024, threshold_l=2, parties_t=4)
    public_key = keys.public_key
    n = public_key.n
    # 份额密钥列表
    private_key = keys.private_keys  #三个参与方，有三个密钥份额
    #EIBF1 = BloomFilter(m_bits=bloom_filter_1.m_bits, k_hashes=bloom_filter_1.k_hashes)
    #EIBF2 = BloomFilter(m_bits=bloom_filter_1.m_bits, k_hashes=bloom_filter_1.k_hashes)

    EBF1 = bloom_filter_1.threshold_paillier_encrypt_all(public_key)
    EBF2 = bloom_filter_2.threshold_paillier_encrypt_all(public_key)
    EBF3 = bloom_filter_3.threshold_paillier_encrypt_all(public_key)

    EBF = [EBF1,EBF2,EBF3]
    # 对 server_set 中的元素进行处理
    total_encrypted_sum = threshold_paillier.encrypt(0, public_key)  # 初始化加密结果为 0
    #temp = threshold_paillier.encrypt(0, public_key)  # 初始化加密结果为 0
    scp1_temp = threshold_paillier.encrypt(0, public_key)
    T_MPSI = []
    for element in server_set:
        for client in range(parties_t-1):
            #计算元素 在一个EBF上的 所有标志位求和
            for i in range(bloom_filter_1.k_hashes):  # 对每个元素进行三次哈希
                index = bloom_filter_1.hash(element, i + 1) % bloom_filter_1.m_bits
                #print(f"element = {element}, index = {index}")
                encrypted_value = EBF[client][index]
                total_encrypted_sum = threshold_paillier.add_homomorphically(total_encrypted_sum,encrypted_value,public_key)
            '''decryption_shares = []
            for i in range(parties_t):
                decryption_shares.append(
                    (mpz(i + 1), partial_decrypt(total_encrypted_sum, keys.public_key, keys.private_keys[i])))
            decrypted_result = threshold_paillier.combine_partial_decrypt(decryption_shares, keys.public_key)
            print(f"element = {element}, EBF{client}, status = {decrypted_result}")'''
            #total_encrypted_sum 为(C_1)^1
            #比较(C_1)^1 与 h_hashes 大小关系 ,temp=Enc(a11)  判断元素是否为 服务器和Pi之间的交集
            temp = secure_comparison_protocol(total_encrypted_sum, encrypt(k_hashes-1, public_key), threshold_l, parties_t, keys)

            '''decryption_shares = []
            for i in range(parties_t):
                decryption_shares.append(
                    (mpz(i + 1), partial_decrypt(total_encrypted_sum, keys.public_key, keys.private_keys[i])))
            decrypted_result = threshold_paillier.combine_partial_decrypt(decryption_shares, keys.public_key)
            print(f"element = {element}, EBF{client}, status = {decrypted_result}, scp(total_encrypted_sum) = {decrypted_result>0}")
'''
            scp1_temp = threshold_paillier.add_homomorphically(scp1_temp, temp, public_key)
            #计服务器计算完一个元素，即element的三个哈希函数对应位置的数据都同态加性求和
            #对于每一个元素的标志位求和，进行SCP协议，判断是否为交集元素。
        '''decryption_shares = []
        for i in range(parties_t):
            decryption_shares.append((mpz(i + 1), partial_decrypt(scp1_temp, keys.public_key, keys.private_keys[i])))
        decrypted_result = threshold_paillier.combine_partial_decrypt(decryption_shares, keys.public_key)
        print(f"element = {element}, scp1_Temp = {scp1_temp}")'''
        scp2 = secure_comparison_protocol(scp1_temp, encrypt(threshold_l, public_key), threshold_l, parties_t, keys)

        decryption_shares = []
        for i in range(parties_t):
            decryption_shares.append(
                (mpz(i + 1), partial_decrypt(scp2, keys.public_key, keys.private_keys[i])))
        decrypted_result = threshold_paillier.combine_partial_decrypt(decryption_shares, keys.public_key)
        #print(f"element = {element}, EBF{client}, status = {decrypted_result}, scp2 = {scp2}")
        #temp = threshold_paillier.encrypt(0, public_key)  # 初始化加密结果为 0
        total_encrypted_sum = threshold_paillier.encrypt(0, public_key)  # 初始化加密结果为 0
        scp1_temp = threshold_paillier.encrypt(0, public_key)
        scp2 = rerandomize(scp2, public_key)
        #部分解密
        decryption_shares = []
        for i in range(parties_t):
            decryption_shares.append((mpz(i + 1), partial_decrypt(scp2, keys.public_key, keys.private_keys[i])))
        decrypted_result = threshold_paillier.combine_partial_decrypt(decryption_shares, keys.public_key)
        #print(f"decryped_shares = {decrypted_result}")
        if int(decrypted_result) == 1:
            T_MPSI.append(element)
    print("T-MPSI = ", T_MPSI)





if __name__ == "__main__":
    main()
